package com.stanford.ml;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.stanford.data.User;

/**
 * Statistics is a utility class that contains basic statistical
 * methods to describe data
 * 
 * @author Fatih Sunor
 */
public class Statistics {
	
	/**
	 * Calculates the Pearson product-moment correlation coefficient
	 * between two arrays of integers.
	 * @param numeric1 is the first array of integers
	 * @param numeric2 is the second array of integers
	 * @return the correlation coefficient
	 */
	public static double correlation(Integer[] numeric1, Integer[] numeric2){
		double result = 0;
        double sumSq1 = 0;
        double sumSq2 = 0;
        double sumCoproduct = 0;
        double mean1 = numeric1[0];
        double mean2 = numeric2[0];
        for(int i=2;i<numeric1.length+1;i+=1){
            double sweep =Double.valueOf(i-1)/i;
            double delta1 = numeric1[i-1]-mean1;
            double delta2 = numeric2[i-1]-mean2;
            sumSq1 += delta1 * delta1 * sweep;
            sumSq2 += delta2 * delta2 * sweep;
            sumCoproduct += delta1 * delta2 * sweep;
            mean1 += delta1 / i;
            mean2 += delta2 / i;
        }
        double sd1 = (double) Math.sqrt(sumSq1/numeric1.length);
        double sd2 = (double) Math.sqrt(sumSq2/numeric1.length);
        double cov = sumCoproduct / numeric1.length;
        result = cov / (sd1*sd2);
        return result;
    }
	
	/** 
	 * Returns the maximum value in an integer array
	 * @param numeric is an array of integers
	 * @return the maximum value in a given integer array
	 */
	public static int max(Integer[] numeric) {
	    int maximum = numeric[0];
	    for (int i=1; i<numeric.length; i++) {
	        if (numeric[i] > maximum) {
	            maximum = numeric[i];
	        }
	    }
	    return maximum;
	}
	
	/** 
	 * Returns the minimum value in an integer array
	 * @param numeric is an array of integers
	 * @return the minimum value in a given integer array
	 */
	public static int min(Integer[] numeric) {
		int minimum = numeric[0];
	    for (int i=1; i<numeric.length; i++) {
	        if (numeric[i] < minimum) {
	            minimum = numeric[i];
	        }
	    }
	    return minimum;
	}
	
	/**
	 * Calculates the mean rating for a set of users
	 * @param users is a list of users
	 * @param type is the appreciation type
	 * @return
	 */
	public static double meanRating(List<User> users, int type){
		int count = 0;
		for(User user: users){
			if(user.getRating()==type){
				count++;
			}
		}
		return (double)count/(double)users.size();
	}
	
	/**
	 * Calculates the female and male ratio for a set of users
	 * @param users is a list of users
	 * @param gender is 1 for male and 2 for female
	 */
	public static double genderRatio(List<User> users, int gender){
		int count = 0;
		for(User user: users){
			if(user.getGender()==gender){
				count++;
			}
		}
		return (double)count/(double)users.size();
	}
	
	/**
	 * Calculates the occurrence frequencies of certain phrases on 
	 * a list. This method can be employed for frequency of 
	 * @return a Map<String, Double> where the value is a relative
	 * frequency of a phrase in the key section.
	 */
	public static Map<String, Double> countRatio(List<String> phrases){
		Map<String, Double> counts = new HashMap<String, Double>();
		double countRatio = 0;
		for(String phrase: phrases){
			if(counts.containsKey(phrase)){
				countRatio=(counts.get(phrase)*phrases.size()+1)/phrases.size();
				counts.put(phrase, countRatio);
			}else{
				counts.put(phrase, 1.0/(double) phrases.size());
			}
		}
		return counts;
	}
}
